<template>
  <span
    ref="currScore"
    class="current-score"
    :class="{ show: hidden, offset: !hidden && paused, died: health <= 0 }"
  >
    <span class="text">当前得分: </span>
    {{ prettifyScore(currentScore) }} 分
  </span>
  <span
    ref="currHealth"
    class="current-health"
    :class="{ show: hidden, offset: !hidden && paused, died: health <= 0 }"
  >
  </span>
  <Health :maxHealth="maxHealth" :health="health" :hidden="hidden" />
  <div class="pause-helper">
    <p :class="{ anim: hidden }">按 回车/空格 暂停</p>
    <button
      @click="$emit('pause')"
      :class="{ show: hidden }"
      class="mobile-pause"
    >
      <v-icon icon="mdi-menu"></v-icon>
    </button>
  </div>
  <div
    class="overlay-container"
    :class="{ fade: overlayState === 1, hide: overlayState === 2 }"
  >
    <v-toolbar class="navbar" height="72">
      <div class="nav-brand">
        <button class="btn-logo" @click="$emit('switch')">
          <img src="/logo_white.svg" alt="Ninjia logo" class="logo" />
        </button>
        <v-tooltip text="Ninjia is open-source!" location="top">
          <template v-slot:activator="{ props }">
            <v-btn
              href="https://gitee.com/Zeiion/Ninjia"
              target="_blank"
              @click="$emit('toggleCursor')"
              v-bind="props"
              density="compact"
              icon="mdi-github"
            />
          </template>
        </v-tooltip>
        <p>
          <img src="/gold.svg" style="height: 40px; vertical-align: middle" />
          {{ Math.floor(globalStore.money) }}
        </p>
      </div>
      <div class="score">
        <p>
          您的最高得分:
          <span class="highlight">{{ prettifyScore(highestScore) }} pts</span>
        </p>
        <p>
          您的上次得分:
          <span class="highlight">{{ prettifyScore(lastScore) }} pts</span>
        </p>
      </div>
      <div class="options">
        <v-menu
          :close-on-content-click="false"
          location="bottom end"
          :offset="[10, 10]"
        >
          <template v-slot:activator="{ props }">
            <v-btn density="comfortable" icon="mdi-cog" v-bind="props" />
          </template>
          <div class="menu-options">
            <p class="title">设置</p>
            <div class="form-group">
              <v-text-field
                v-model="settings.username"
                label="用户名"
                hide-details="auto"
                color="rgb(182, 227, 196)"
                maxLength="16"
              ></v-text-field>
            </div>
            <div class="form-group">
              <v-slider
                v-model="settings.sensitivity"
                label="敏感度"
                color="#70A480"
                track-color="#fff"
                step="0.1"
                min="0.5"
                max="2.0"
                style="margin: 0; margin-right: 20px"
              ></v-slider>
              <span class="sensitivity-value">{{ settings.sensitivity }}</span>
            </div>
            <div class="form-group mb-0">
              <label for="rushMode">勇者模式</label>
              <input
                v-model="settings.rushMode"
                id="rushMode"
                class="checkbox"
                type="checkbox"
              />
            </div>
            <small>加快了游戏速度，但获得的分数也更高。</small>
            <div class="form-group">
              <div style="flex-grow: 1">
                <v-select
                  v-model="settings.graphicsPreset"
                  label="游戏画质"
                  color="rgb(182, 227, 196)"
                  :items="graphicsOptions"
                  :disabled="paused"
                ></v-select>
                <span v-if="paused" class="disabled-helper"
                  >Disabled while in-game</span
                >
              </div>
            </div>
          </div>
        </v-menu>
        <v-tooltip
          :text="fullscreen ? 'Minimize' : 'Go fullscreen'"
          location="top"
        >
          <template v-slot:activator="{ props }">
            <v-btn
              @click="$emit('toggleFullscreen')"
              v-bind="props"
              density="comfortable"
              :icon="fullscreen ? 'mdi-fullscreen-exit' : 'mdi-fullscreen'"
            />
          </template>
        </v-tooltip>
        <v-tooltip
          :text="
            props.settings.showCursor
              ? 'Hide cursor in-game'
              : 'Show cursor in-game'
          "
          location="bottom left"
        >
          <template v-slot:activator="{ props }">
            <v-btn
              v-bind="props"
              density="comfortable"
              @click="settings.showCursor = !settings.showCursor"
              :icon="
                settings.showCursor ? 'mdi-cursor-default-outline' : 'mdi-sword'
              "
            />
          </template>
        </v-tooltip>
      </div>
    </v-toolbar>
    <div class="buttons">
      <ButtonSlash
        :text="paused ? '继续前进' : '开始征途'"
        @click="$emit('start')"
      />
      <ButtonSlash
        v-if="paused"
        :alt="true"
        text="重新开始"
        @click="$emit('reset')"
      />
    </div>

    <div class="gesture">
      <Gesture
        :handle-gesture-move="handleGestureMove"
        class="gesture"
      ></Gesture>
    </div>

    <div class="your-sword" :class="{ hide: !swordMenuOpen }">
      <SwordMenu :settings="settings" :paused="paused" />
      <button class="btn-open" @click="swordMenuOpen = !swordMenuOpen">
        <v-icon icon="mdi-chevron-right" v-if="!swordMenuOpen" />
        <v-icon icon="mdi-chevron-left" v-else />
      </button>
    </div>
    <div class="leaderboard">
      <LeaderBoard compact="true" ref="leaderBoard" />
    </div>
    <p v-if="paused" class="paused-text">Paused</p>
  </div>
</template>

<script setup lang="ts">
import { Settings } from '../game/models/Settings';
import ButtonSlash from './ButtonSlash.vue';
import Gesture from './Gesture.vue';
import Health from './Health.vue';
import LeaderBoard from './LeaderBoard.vue';
import SwordMenu from './SwordMenu.vue';
import { watch } from 'vue';
import { ref } from 'vue';
import { reactive } from 'vue';
import GestureEvent from '~/game/models/GestureEvent';
import { prettifyScore } from '~/libs/helpers';
import { useGlobalStore } from '~/libs/stores/global';
import { GraphicsPreset } from '~/libs/types/GraphicsPresset';

const emit = defineEmits([
  'switch',
  'start',
  'reset',
  'toggleFullscreen',
  'toggleCursor',
  'updateSettings',
  'pause',
]);
const props = defineProps<{
  hidden: boolean;
  paused: boolean;
  currentScore: number;
  fullscreen: boolean;
  settings: Settings;
  maxHealth: number;
  health: number;
  lastScore: number;
  highestScore: number;
  addedScore: { value: number };
  handleGestureMove: (e: MouseEvent | GestureEvent | TouchEvent) => void;
  addedHealth: { value: number };
}>();

const overlayState = ref(-1);
const currScore = ref(null);
const currHealth = ref(null);
const swordMenuOpen = ref(window.innerWidth > 1200);
const settings = reactive(props.settings);
const leaderBoard = ref();

const globalStore = useGlobalStore();

const graphicsOptions = Object.values(GraphicsPreset);

watch(
  () => props.addedScore,
  () => {
    if (currScore.value) {
      const score = document.createElement('span');
      score.classList.add('added-score');
      score.innerHTML = '+' + props.addedScore.value.toString();
      (currScore.value as HTMLElement).appendChild(score);
      setTimeout(() => {
        if (currScore.value) {
          (currScore.value as HTMLElement).removeChild(score);
        }
      }, 1200);
    }
  },
);

watch(
  () => props.addedHealth,
  () => {
    if (currHealth.value && props.addedHealth.value > 0) {
      const health = document.createElement('div');
      health.classList.add('added-health');
      health.innerHTML = `+${
        props.addedHealth.value > 1 ? props.addedHealth.value : ''
      }❤`;
      (currHealth.value as HTMLElement).appendChild(health);
      setTimeout(() => {
        if (currHealth.value) {
          (currHealth.value as HTMLElement).removeChild(health);
        }
      }, 1200);
    }
  },
);

watch(
  () => props.settings,
  () => {
    settings.replace(props.settings);
  },
);

watch(settings, () => {
  emit('updateSettings', settings);
});

watch(
  () => props.hidden,
  () => {
    if (props.hidden) {
      if (overlayState.value === -1) {
        overlayState.value = 1;
        setTimeout(() => {
          overlayState.value = 2;
        }, 500);
      } else {
        overlayState.value = 2;
      }
    } else {
      overlayState.value = 0;
    }
  },
);

window.addEventListener('resize', () => {
  if (!swordMenuOpen.value) {
    swordMenuOpen.value = window.innerWidth > 1200;
  }
});

function submitRun(settings: Settings, score: number) {
  leaderBoard.value?.submitNewRun(settings, score);
}

defineExpose({
  submitRun,
});
</script>

<style scoped lang="scss">
.nav-brand {
  display: flex;
  align-items: center;
  gap: 30px;

  .v-btn {
    font-size: 20px;
  }

  img {
    user-select: none;
    -webkit-user-drag: none;
    -webkit-user-select: none;
  }
}

.pause-helper {
  position: absolute;
  top: 10px;
  right: 10px;
  color: #fff;

  button {
    border: 0;
    background-color: transparent;
  }

  p {
    display: none;
    pointer-events: none;

    &.anim {
      animation: helper-fade 1200ms ease 3000ms forwards;
    }
  }

  @media (hover: hover) {
    button {
      display: none;
    }
    p {
      display: block;
    }
  }
}

@keyframes helper-fade {
  0% {
    transform: translateY(0);
    opacity: 1;
  }
  100% {
    transform: translateY(-10px);
    opacity: 0;
  }
}

.current-score,
.current-health {
  display: flex;
  position: absolute;
  top: -50px;
  left: 50%;
  transform: translateX(-50%);
  pointer-events: none;
  -webkit-user-drag: none;
  -moz-user-drag: none;
  z-index: 5;
  transition: top 300ms ease;
  font-weight: 400;
  font-size: 25px;
  font-family: 'Bree serif';
  text-shadow: 0 4px rgba(#000, 0.25);

  .text {
    display: block;
    opacity: 0;
    transition:
      width 350ms ease,
      opacity 200ms ease;
    width: 0;
    overflow: hidden;
    white-space: nowrap;
  }

  &.show {
    top: 10px;
  }

  &.offset {
    top: 80px;
    font-size: 22px;

    .text {
      opacity: 1;
      width: 200px;
    }
  }

  &.died {
    top: -60px;
  }
}

@media (max-width: 768px) {
  .current-score {
    &.offset {
      top: 150px;
    }
  }
}

@media (max-width: 560px) {
  .current-score {
    &.offset {
      left: 20px;
      transform: none;
    }
  }
}

.overlay-container {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 1;
  backdrop-filter: blur(8px);
  transition: opacity 500ms ease;
  background-color: rgba(#000, 0.6);
  width: 100vw;
  height: 100vh;

  &.fade {
    opacity: 0;
  }

  &.hide {
    display: none;
  }
}

.navbar {
  position: relative;
  background-color: transparent;
  padding: 20px 26px;
  overflow: visible;
  color: #fff;

  .btn-logo {
    max-width: 160px;
    height: 100%;
    img {
      width: 100%;
      height: 100%;
      object-fit: contain;
    }
  }

  .score {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    font-weight: 400;
    text-align: center;

    .highlight {
      color: var(--primary);
    }
  }

  .options {
    display: flex;
    align-items: flex-start;
    gap: 15px;
    height: 100%;
  }
}

@media (max-width: 768px) {
  .navbar {
    .score {
      top: 75px;
    }
  }
}

@media (max-width: 560px) {
  .navbar {
    .options {
      flex-direction: column;
    }

    .score {
      left: 0;
      transform: none;
    }
  }
}

.buttons {
  display: flex;
  position: absolute;
  top: 50%;
  left: 50%;
  flex-direction: column;
  gap: 50px;
  transform: translateX(-50%);
}

@media (max-width: 1400px) {
  .buttons {
    top: 60%;
  }
}

.your-sword {
  position: absolute;
  top: 50%;
  left: 20px;
  transform: translateY(-50%);
  transition: transform 400ms ease;

  .btn-open {
    display: none;
    position: absolute;
    top: 50%;
    right: -65px;
    transform: translateY(-50%);
    transition: right 400ms ease;
    border-radius: 50%;
    background-color: var(--primary);
    width: 48px;
    height: 48px;
  }

  &.hide {
    transform: translate(calc(-100% - 120px), -50%);

    .btn-open {
      right: -155px;
    }
  }
}

@media (max-width: 1200px) {
  .your-sword {
    .btn-open {
      display: block;
    }
  }
}

@media (max-width: 1000px) {
  .your-sword {
    top: 0;
    left: 0;
    transform: none;
    background-color: #fff;
    height: 100%;
    color: #000;

    &.hide {
      transform: translate(calc(-100% - 120px), 0);

      .btn-open {
        right: -175px;
      }
    }
  }
}

.leaderboard {
  position: absolute;
  top: 40%;
  right: 30px;
  transform: translateY(-50%);

  @media (max-width: 1000px) {
    top: unset;
    right: 0;
    bottom: 5px;
    transform: none;
  }

  @media (max-width: 768px) {
    display: none;
  }
}

.menu-options {
  backdrop-filter: blur(6px);
  border: 2px solid #fff;
  background-color: rgba(#000, 0.3);
  padding: 12px 15px 20px;
  min-width: 320px;
  color: #fff;

  .title {
    font-size: 20px;
    text-align: center;
  }

  small {
    margin-bottom: 10px;
    padding: 0 40px 0 10px;
    font-weight: 300;
  }

  .form-group {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    margin: 20px 0;
    padding: 0 10px;
    width: 100%;

    label {
      display: flex;
      flex-grow: 1;
      align-items: center;
    }

    .v-input {
      flex-grow: 1;
    }

    .checkbox {
      display: flex;
      appearance: none;
      cursor: pointer;
      margin-right: 10px;
      border: 2px solid #fff;
      width: 1.75em;
      height: 1.75em;

      &:checked {
        background-image: url('/icons/check.svg');
        background-position: center;
        background-size: contain;
        background-size: cover;
        background-repeat: no-repeat;
        background-color: rgba(#fff, 0.1);
      }

      &:target {
        transform: sclae(0.9);
      }
    }

    &.mb-0 {
      margin-bottom: 0;
    }
  }
}

.paused-text {
  position: absolute;
  top: 25%;
  left: 50%;
  transform: translate(-50%, -50%);
  margin: 0;
  color: rgba(#fff, 0.05);
  font-weight: 400;
  font-size: 168px;
  font-family: 'Bree serif';
  letter-spacing: 5px;
  user-select: none;
  -webkit-user-drag: none;
  -moz-user-drag: none;
  pointer-events: none;
}

@media (max-width: 560px) {
  .paused-text {
    font-size: 25vw;
  }
}

.disabled-helper {
  color: rgba(#fff, 0.5);
  font-size: 12px;
}

.sensitivity-value {
  flex-basis: 25px;
  text-align: right;
}

.gesture {
  display: flex;
  position: absolute;
  top: 8%;
  left: 90%;
  flex-direction: column;
  gap: 50px;
  transform: translateX(-50%);
  width: 200px;
}

@media (max-width: 1400px) {
  .gesture {
    top: 60%;
  }
}

@media (max-width: 1000px) {
  .gesture {
    top: 15%;
    left: 85%;
  }
}
</style>
